﻿using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace WebAppWeChatDemo.Models
{
    
    public class WeChartHelper
    {
        public delegate void CompletedHandler(SendMessageModel model);
        /// <summary>
        /// 发送完成后的回调事件
        /// </summary>
        public CompletedHandler SendCompletedEvent;
        private MessageQueue messageQueue = new MessageQueue();
        private Logger logger = LogManager.GetCurrentClassLogger();
        /// <summary>
        /// 将消息加入到队列
        /// </summary>
        /// <param name="model"></param>
        public void AddMessage(SendMessageModel model)
        {
            Message msg = new Message();
            string appid = WeChartConfig.AppID;
            string secret = WeChartConfig.AppSecret;
            if (null != model)
            {
                appid = model.appid;
                secret = model.appsecret;
                msg.touser = model.openid;
                msg.template_id = model.template_id;
                var data = JsonConvert.DeserializeObject<Dictionary<string, DataModel>>(model.message);
                msg.data = data;
            }
            else
            {
                msg.data.Add("name", new DataModel
                {
                    value = "ZainZhou",
                    color = "#173177"
                });
                msg.data.Add("time", new DataModel
                {
                    value = "20分钟",
                    color = "#ff0000"
                });
            }
            logger.Info($"添加一条消息到队列：AppID：{appid},OpenId:{msg.touser},Message:{model.message}");
            messageQueue.AddMessgae(new MessageQueueModel(msg,model));
        }
        /// <summary>
        /// 异步发送消息
        /// </summary>
        /// <returns></returns>
        public async Task SendMessageAsync()
        {
            if(messageQueue.IsMessageQueueAvailable)
            {
                MessageQueueModel model = messageQueue.GetMessage();
                logger.Info($"准备发送消息：AppID：{model.sendMessageModel.appid},OpenId:{model.message.touser},Message:{model.sendMessageModel.message}");
                string token = await TokenHelper.GetAccessTokenAsync(model.sendMessageModel.appid, model.sendMessageModel.appsecret);

                string url = $"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={token}";
                string postData = JsonConvert.SerializeObject(model.message);
                string str = await HttpPostData(url, postData);
                logger.Info($"返回结果：{str}");
                SendCompletedEvent?.Invoke(model.sendMessageModel);
            }
            else
            {
                logger.Info($"队列中没有待发送消息");
            }
        }
        public async Task<string> HttpPostData(string posturl, string postData)
        {
            Stream outstream = null;
            Stream instream = null;
            StreamReader sr = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            Encoding encoding = Encoding.UTF8;
            byte[] data = encoding.GetBytes(postData);
            // 准备请求...
            try
            {
                // 设置参数
                request = WebRequest.Create(posturl) as HttpWebRequest;
                CookieContainer cookieContainer = new CookieContainer();
                request.CookieContainer = cookieContainer;
                request.AllowAutoRedirect = true;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = data.Length;
                outstream = await request.GetRequestStreamAsync();
                outstream.Write(data, 0, data.Length);
                outstream.Close();
                response = request.GetResponse() as HttpWebResponse;
                instream = response.GetResponseStream();
                sr = new StreamReader(instream, encoding);
                string content = sr.ReadToEnd();
                string err = string.Empty;
                return content;
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return string.Empty;
            }
        }

    }

    public static class WeChartConfig
    {
        public const string AppID = "wx8c3d6207dc42d2bd";
        public const string AppSecret = "e9b2746cadca984cfa966f2623daa908";
    }
    /// <summary>
    /// 获取ACCOUNT
    /// </summary>
    public static class TokenHelper
    {
        private static TokenModel ACCESSTOKEN = null;

        public static async Task<string> GetAccessTokenAsync(string appid = "", string secret = "")
        {
            
            appid = string.IsNullOrEmpty(appid) ? WeChartConfig.AppID : appid;
            secret = string.IsNullOrEmpty(secret) ? WeChartConfig.AppSecret : secret;
            string access_token_url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";
            if (null == ACCESSTOKEN)
            {
                ACCESSTOKEN = new TokenModel();
            }
            if (ACCESSTOKEN.Date.AddMonths(115) > DateTime.Now)
            {
                var client = new WebClient();
                var str = await client.DownloadStringTaskAsync(access_token_url);
                var resJson = JsonConvert.DeserializeObject<dynamic>(str);
                ACCESSTOKEN.Token = resJson["access_token"];
            }
            return ACCESSTOKEN.Token;
        }
    }

    public class MessageQueue
    {
        private readonly static Queue<MessageQueueModel> messageQueue = new Queue<MessageQueueModel>();
        /// <summary>
        /// 添加一条消息到队列
        /// </summary>
        /// <param name="msg"></param>
        public void AddMessgae(MessageQueueModel msg)
        {
            lock(this)
            {
                messageQueue.Enqueue(msg);
            }
        }

        public MessageQueueModel GetMessage()
        {
            MessageQueueModel msg = default(MessageQueueModel);
            lock(this)
            {
                msg = messageQueue.Dequeue();
            }
            return msg;
        }

        public bool IsMessageQueueAvailable => messageQueue.Count > 0;
    }

    public class TokenModel
    {
        public TokenModel()
        {
            Date = DateTime.Now;
        }
        public DateTime Date { get; set; }

        public string Token { get; set; }
    }

    public class MessageQueueModel
    {
        public Message message { get; set; }

        public SendMessageModel sendMessageModel { get; set; }

        public MessageQueueModel(Message msg,SendMessageModel config)
        {
            message = msg;
            sendMessageModel = config;
        }
    }

    public class Message
    {
        public Message()
        {
            data = new Dictionary<string, DataModel>();
        }
        public string touser { get; set; } = "ozrY05rmUVHbade_tLk5iIaVaDcE";
        public string template_id { get; set; } = "NvQeUx4xEAQ-XBZUdhN0X1Iyqb4SmP3_LAHE0RxojuQ";
        public string url { get; set; } = "zainzhou.xicp.io/about";

        public string topcolor { get; set; } = "#FF0000";

        public Dictionary<string, DataModel> data { get; set; }
    }

    public class DataModel
    {
        public string value { get; set; }

        public string color { get; set; }
    }
}